import 'dart:convert';
import 'package:shared_preferences/shared_preferences.dart';
import '../lara_press_logs.dart';

/// LaraPress 键值数据库封装类
/// 提供 shared_preferences 的便捷封装，支持各种数据类型的存储和读取
class LaraPressKeyDB {
  static LaraPressKeyDB? _instance;
  static SharedPreferences? _prefs;

  // 私有构造函数
  LaraPressKeyDB._();

  /// 获取单例实例
  static Future<LaraPressKeyDB> getInstance() async {
    try {
      if (_instance == null) {
        _instance = LaraPressKeyDB._();
        _prefs = await SharedPreferences.getInstance();
      }
      return _instance!;
    } catch (e) {
      LaraPressLogs.getInstance().error(
        'getInstance error: $e',
        tag: 'LaraPressKeyDB',
      );
      throw e;
    }
  }

  /// 确保 SharedPreferences 已初始化
  Future<void> _ensureInitialized() async {
    _prefs ??= await SharedPreferences.getInstance();
  }

  // ==================== 基本数据类型存储 ====================

  /// 存储字符串
  /// [key] 键名
  /// [value] 字符串值
  /// 返回是否存储成功
  Future<bool> setString(String key, String value) async {
    try {
      await _ensureInitialized();
      return await _prefs!.setString(key, value);
    } catch (e) {
      LaraPressLogs.getInstance().error(
        'setString error: $e',
        tag: 'LaraPressKeyDB',
      );
      return false;
    }
  }

  /// 获取字符串
  /// [key] 键名
  /// [defaultValue] 默认值
  /// 返回字符串值或默认值
  Future<String> getString(String key, {String defaultValue = ''}) async {
    try {
      await _ensureInitialized();
      return _prefs!.getString(key) ?? defaultValue;
    } catch (e) {
      logs.error('getString error: $e', tag: 'LaraPressKeyDB');
      return defaultValue;
    }
  }

  /// 存储整数
  /// [key] 键名
  /// [value] 整数值
  /// 返回是否存储成功
  Future<bool> setInt(String key, int value) async {
    try {
      await _ensureInitialized();
      return await _prefs!.setInt(key, value);
    } catch (e) {
      logs.error('setInt error: $e', tag: 'LaraPressKeyDB');
      return false;
    }
  }

  /// 获取整数
  /// [key] 键名
  /// [defaultValue] 默认值
  /// 返回整数值或默认值
  Future<int> getInt(String key, {int defaultValue = 0}) async {
    try {
      await _ensureInitialized();
      return _prefs!.getInt(key) ?? defaultValue;
    } catch (e) {
      logs.error('getInt error: $e', tag: 'LaraPressKeyDB');
      return defaultValue;
    }
  }

  /// 存储浮点数
  /// [key] 键名
  /// [value] 浮点数值
  /// 返回是否存储成功
  Future<bool> setDouble(String key, double value) async {
    try {
      await _ensureInitialized();
      return await _prefs!.setDouble(key, value);
    } catch (e) {
      logs.error('setDouble error: $e', tag: 'LaraPressKeyDB');
      return false;
    }
  }

  /// 获取浮点数
  /// [key] 键名
  /// [defaultValue] 默认值
  /// 返回浮点数值或默认值
  Future<double> getDouble(String key, {double defaultValue = 0.0}) async {
    try {
      await _ensureInitialized();
      return _prefs!.getDouble(key) ?? defaultValue;
    } catch (e) {
      logs.error('getDouble error: $e', tag: 'LaraPressKeyDB');
      return defaultValue;
    }
  }

  /// 存储布尔值
  /// [key] 键名
  /// [value] 布尔值
  /// 返回是否存储成功
  Future<bool> setBool(String key, bool value) async {
    try {
      await _ensureInitialized();
      return await _prefs!.setBool(key, value);
    } catch (e) {
      logs.error('setBool error: $e', tag: 'LaraPressKeyDB');
      return false;
    }
  }

  /// 获取布尔值
  /// [key] 键名
  /// [defaultValue] 默认值
  /// 返回布尔值或默认值
  Future<bool> getBool(String key, {bool defaultValue = false}) async {
    try {
      await _ensureInitialized();
      return _prefs!.getBool(key) ?? defaultValue;
    } catch (e) {
      logs.error('getBool error: $e', tag: 'LaraPressKeyDB');
      return defaultValue;
    }
  }

  // ==================== 集合类型存储 ====================

  /// 存储字符串列表
  /// [key] 键名
  /// [value] 字符串列表
  /// 返回是否存储成功
  Future<bool> setStringList(String key, List<String> value) async {
    try {
      await _ensureInitialized();
      return await _prefs!.setStringList(key, value);
    } catch (e) {
      logs.error('setStringList error: $e', tag: 'LaraPressKeyDB');
      return false;
    }
  }

  /// 获取字符串列表
  /// [key] 键名
  /// [defaultValue] 默认值
  /// 返回字符串列表或默认值
  Future<List<String>> getStringList(
    String key, {
    List<String>? defaultValue,
  }) async {
    try {
      await _ensureInitialized();
      return _prefs!.getStringList(key) ?? defaultValue ?? [];
    } catch (e) {
      logs.error('getStringList error: $e', tag: 'LaraPressKeyDB');
      return defaultValue ?? [];
    }
  }

  /// 存储 Map 对象（转换为 JSON 字符串存储）
  /// [key] 键名
  /// [value] Map 对象
  /// 返回是否存储成功
  Future<bool> setMap(String key, Map<String, dynamic> value) async {
    try {
      await _ensureInitialized();
      String jsonString = jsonEncode(value);
      return await _prefs!.setString(key, jsonString);
    } catch (e) {
      logs.error('setMap error: $e', tag: 'LaraPressKeyDB');
      return false;
    }
  }

  /// 获取 Map 对象（从 JSON 字符串解析）
  /// [key] 键名
  /// [defaultValue] 默认值
  /// 返回 Map 对象或默认值
  Future<Map<String, dynamic>> getMap(
    String key, {
    Map<String, dynamic>? defaultValue,
  }) async {
    try {
      await _ensureInitialized();
      String? jsonString = _prefs!.getString(key);
      if (jsonString == null) {
        return defaultValue ?? {};
      }
      return jsonDecode(jsonString) as Map<String, dynamic>;
    } catch (e) {
      logs.error('getMap error: $e', tag: 'LaraPressKeyDB');
      return defaultValue ?? {};
    }
  }

  /// 存储对象列表（转换为 JSON 字符串存储）
  /// [key] 键名
  /// [value] 对象列表
  /// 返回是否存储成功
  Future<bool> setObjectList(
    String key,
    List<Map<String, dynamic>> value,
  ) async {
    try {
      await _ensureInitialized();
      String jsonString = jsonEncode(value);
      return await _prefs!.setString(key, jsonString);
    } catch (e) {
      logs.error('setObjectList error: $e', tag: 'LaraPressKeyDB');
      return false;
    }
  }

  /// 获取对象列表（从 JSON 字符串解析）
  /// [key] 键名
  /// [defaultValue] 默认值
  /// 返回对象列表或默认值
  Future<List<Map<String, dynamic>>> getObjectList(
    String key, {
    List<Map<String, dynamic>>? defaultValue,
  }) async {
    try {
      await _ensureInitialized();
      String? jsonString = _prefs!.getString(key);
      if (jsonString == null) {
        return defaultValue ?? [];
      }
      List<dynamic> list = jsonDecode(jsonString) as List<dynamic>;
      return list.cast<Map<String, dynamic>>();
    } catch (e) {
      logs.error('getObjectList error: $e', tag: 'LaraPressKeyDB');
      return defaultValue ?? [];
    }
  }

  // ==================== 通用存储方法 ====================

  /// 存储任意对象（转换为 JSON 字符串存储）
  /// [key] 键名
  /// [value] 任意对象
  /// 返回是否存储成功
  Future<bool> setObject(String key, dynamic value) async {
    try {
      await _ensureInitialized();
      String jsonString = jsonEncode(value);
      return await _prefs!.setString(key, jsonString);
    } catch (e) {
      logs.error('setObject error: $e', tag: 'LaraPressKeyDB');
      return false;
    }
  }

  /// 获取任意对象（从 JSON 字符串解析）
  /// [key] 键名
  /// [defaultValue] 默认值
  /// 返回对象或默认值
  Future<T> getObject<T>(String key, {T? defaultValue}) async {
    try {
      await _ensureInitialized();
      String? jsonString = _prefs!.getString(key);
      if (jsonString == null) {
        return defaultValue as T;
      }
      return jsonDecode(jsonString) as T;
    } catch (e) {
      logs.error('getObject error: $e', tag: 'LaraPressKeyDB');
      return defaultValue as T;
    }
  }

  // ==================== 批量操作 ====================

  /// 批量存储数据
  /// [data] 要存储的数据 Map
  /// 返回存储成功的数量
  Future<int> setBatch(Map<String, dynamic> data) async {
    try {
      await _ensureInitialized();
      int successCount = 0;

      for (String key in data.keys) {
        dynamic value = data[key];
        bool success = false;

        if (value is String) {
          success = await setString(key, value);
        } else if (value is int) {
          success = await setInt(key, value);
        } else if (value is double) {
          success = await setDouble(key, value);
        } else if (value is bool) {
          success = await setBool(key, value);
        } else if (value is List<String>) {
          success = await setStringList(key, value);
        } else {
          success = await setObject(key, value);
        }

        if (success) successCount++;
      }

      return successCount;
    } catch (e) {
      logs.error('setBatch error: $e', tag: 'LaraPressKeyDB');
      return 0;
    }
  }

  /// 批量获取数据
  /// [keys] 键名列表
  /// 返回包含所有键值对的 Map
  Future<Map<String, dynamic>> getBatch(List<String> keys) async {
    try {
      await _ensureInitialized();
      Map<String, dynamic> result = {};

      for (String key in keys) {
        if (_prefs!.containsKey(key)) {
          dynamic value = _prefs!.get(key);
          result[key] = value;
        }
      }

      return result;
    } catch (e) {
      logs.error('getBatch error: $e', tag: 'LaraPressKeyDB');
      return {};
    }
  }

  // ==================== 查询和检查 ====================

  /// 检查键是否存在
  /// [key] 键名
  /// 返回键是否存在
  Future<bool> containsKey(String key) async {
    try {
      await _ensureInitialized();
      return _prefs!.containsKey(key);
    } catch (e) {
      logs.error('containsKey error: $e', tag: 'LaraPressKeyDB');
      return false;
    }
  }

  /// 获取所有键名
  /// 返回所有键名的集合
  Future<Set<String>> getKeys() async {
    try {
      await _ensureInitialized();
      return _prefs!.getKeys();
    } catch (e) {
      logs.error('getKeys error: $e', tag: 'LaraPressKeyDB');
      return <String>{};
    }
  }

  /// 获取所有数据
  /// 返回包含所有键值对的 Map
  Future<Map<String, dynamic>> getAll() async {
    try {
      await _ensureInitialized();
      Map<String, dynamic> result = {};

      for (String key in _prefs!.getKeys()) {
        result[key] = _prefs!.get(key);
      }

      return result;
    } catch (e) {
      logs.error('getAll error: $e', tag: 'LaraPressKeyDB');
      return {};
    }
  }

  // ==================== 删除操作 ====================

  /// 删除指定键
  /// [key] 键名
  /// 返回是否删除成功
  Future<bool> remove(String key) async {
    try {
      await _ensureInitialized();
      return await _prefs!.remove(key);
    } catch (e) {
      logs.error('remove error: $e', tag: 'LaraPressKeyDB');
      return false;
    }
  }

  /// 批量删除键
  /// [keys] 键名列表
  /// 返回删除成功的数量
  Future<int> removeBatch(List<String> keys) async {
    try {
      await _ensureInitialized();
      int successCount = 0;

      for (String key in keys) {
        if (await remove(key)) {
          successCount++;
        }
      }

      return successCount;
    } catch (e) {
      logs.error('removeBatch error: $e', tag: 'LaraPressKeyDB');
      return 0;
    }
  }

  /// 清除所有数据
  /// 返回是否清除成功
  Future<bool> clear() async {
    try {
      await _ensureInitialized();
      return await _prefs!.clear();
    } catch (e) {
      logs.error('clear error: $e', tag: 'LaraPressKeyDB');
      return false;
    }
  }

  // ==================== 工具方法 ====================

  /// 重新加载 SharedPreferences
  /// 在数据可能被外部修改时使用
  Future<void> reload() async {
    try {
      await _prefs?.reload();
    } catch (e) {
      logs.error('reload error: $e', tag: 'LaraPressKeyDB');
    }
  }

  /// 获取存储大小（估算）
  /// 返回存储的键值对数量
  Future<int> getSize() async {
    try {
      await _ensureInitialized();
      return _prefs!.getKeys().length;
    } catch (e) {
      logs.error('getSize error: $e', tag: 'LaraPressKeyDB');
      return 0;
    }
  }

  /// 检查存储是否为空
  /// 返回存储是否为空
  Future<bool> isEmpty() async {
    try {
      await _ensureInitialized();
      return _prefs!.getKeys().isEmpty;
    } catch (e) {
      logs.error('isEmpty error: $e', tag: 'LaraPressKeyDB');
      return true;
    }
  }

  // ==================== 数据迁移和版本管理 ====================

  /// 数据版本键
  static const String _versionKey = '_lara_press_db_version';

  /// 获取当前数据版本
  Future<int> getVersion() async {
    return await getInt(_versionKey, defaultValue: 1);
  }

  /// 设置数据版本
  Future<bool> setVersion(int version) async {
    return await setInt(_versionKey, version);
  }

  /// 数据迁移
  /// [fromVersion] 当前版本
  /// [toVersion] 目标版本
  /// [migrationCallback] 迁移回调函数
  Future<bool> migrate(
    int fromVersion,
    int toVersion,
    Future<bool> Function(int from, int to) migrationCallback,
  ) async {
    try {
      int currentVersion = await getVersion();
      if (currentVersion < fromVersion) {
        logs.warning(
          'migrate: 当前版本 $currentVersion 小于起始版本 $fromVersion',
          tag: 'LaraPressKeyDB',
        );
        return false;
      }

      if (currentVersion >= toVersion) {
        logs.info(
          'migrate: 当前版本 $currentVersion 已大于等于目标版本 $toVersion',
          tag: 'LaraPressKeyDB',
        );
        return true;
      }

      bool success = await migrationCallback(fromVersion, toVersion);
      if (success) {
        await setVersion(toVersion);
        logs.info(
          'migrate: 成功从版本 $fromVersion 迁移到 $toVersion',
          tag: 'LaraPressKeyDB',
        );
      }
      return success;
    } catch (e) {
      logs.error('migrate error: $e', tag: 'LaraPressKeyDB');
      return false;
    }
  }

  // ==================== 数据验证和类型安全 ====================

  /// 验证键名格式
  bool _isValidKey(String key) {
    return key.isNotEmpty && !key.startsWith('_') && key.length <= 100;
  }

  /// 安全存储字符串（带验证）
  Future<bool> setStringSafe(String key, String value) async {
    if (!_isValidKey(key)) {
      logs.warning('setStringSafe: 无效的键名 $key', tag: 'LaraPressKeyDB');
      return false;
    }
    return await setString(key, value);
  }

  /// 安全获取字符串（带验证）
  Future<String> getStringSafe(String key, {String defaultValue = ''}) async {
    if (!_isValidKey(key)) {
      logs.warning('getStringSafe: 无效的键名 $key', tag: 'LaraPressKeyDB');
      return defaultValue;
    }
    return await getString(key, defaultValue: defaultValue);
  }

  /// 检查数据类型是否匹配
  Future<bool> isTypeMatch(String key, Type expectedType) async {
    try {
      await _ensureInitialized();
      if (!_prefs!.containsKey(key)) return false;

      dynamic value = _prefs!.get(key);
      return value.runtimeType == expectedType;
    } catch (e) {
      logs.error('isTypeMatch error: $e', tag: 'LaraPressKeyDB');
      return false;
    }
  }

  // ==================== 数据备份和恢复 ====================

  /// 导出所有数据为 Map
  Future<Map<String, dynamic>> exportData() async {
    try {
      await _ensureInitialized();
      Map<String, dynamic> exportData = {};

      for (String key in _prefs!.getKeys()) {
        if (!key.startsWith('_')) {
          // 排除内部键
          exportData[key] = _prefs!.get(key);
        }
      }

      return exportData;
    } catch (e) {
      logs.error('exportData error: $e', tag: 'LaraPressKeyDB');
      return {};
    }
  }

  /// 从 Map 导入数据
  Future<int> importData(Map<String, dynamic> data) async {
    try {
      await _ensureInitialized();
      int successCount = 0;

      for (String key in data.keys) {
        if (_isValidKey(key)) {
          dynamic value = data[key];
          bool success = false;

          if (value is String) {
            success = await setString(key, value);
          } else if (value is int) {
            success = await setInt(key, value);
          } else if (value is double) {
            success = await setDouble(key, value);
          } else if (value is bool) {
            success = await setBool(key, value);
          } else if (value is List) {
            if (value is List<String>) {
              success = await setStringList(key, value);
            } else {
              success = await setObject(key, value);
            }
          } else {
            success = await setObject(key, value);
          }

          if (success) successCount++;
        }
      }

      return successCount;
    } catch (e) {
      logs.error('importData error: $e', tag: 'LaraPressKeyDB');
      return 0;
    }
  }

  // ==================== 高级查询功能 ====================

  /// 按前缀查找键
  Future<List<String>> getKeysByPrefix(String prefix) async {
    try {
      await _ensureInitialized();
      return _prefs!.getKeys().where((key) => key.startsWith(prefix)).toList();
    } catch (e) {
      logs.error('getKeysByPrefix error: $e', tag: 'LaraPressKeyDB');
      return [];
    }
  }

  /// 按前缀获取数据
  Future<Map<String, dynamic>> getDataByPrefix(String prefix) async {
    try {
      await _ensureInitialized();
      Map<String, dynamic> result = {};

      for (String key in _prefs!.getKeys()) {
        if (key.startsWith(prefix)) {
          result[key] = _prefs!.get(key);
        }
      }

      return result;
    } catch (e) {
      logs.error('getDataByPrefix error: $e', tag: 'LaraPressKeyDB');
      return {};
    }
  }

  /// 按前缀删除数据
  Future<int> removeByPrefix(String prefix) async {
    try {
      await _ensureInitialized();
      List<String> keysToRemove = await getKeysByPrefix(prefix);
      return await removeBatch(keysToRemove);
    } catch (e) {
      logs.error('removeByPrefix error: $e', tag: 'LaraPressKeyDB');
      return 0;
    }
  }

  // ==================== 统计和监控 ====================

  /// 获取存储统计信息
  Future<Map<String, dynamic>> getStorageStats() async {
    try {
      await _ensureInitialized();
      Set<String> keys = _prefs!.getKeys();
      Map<String, int> typeCount = {};
      int totalSize = 0;

      for (String key in keys) {
        dynamic value = _prefs!.get(key);
        String type = value.runtimeType.toString();
        typeCount[type] = (typeCount[type] ?? 0) + 1;

        // 估算大小
        if (value is String) {
          totalSize += value.length * 2; // UTF-16 字符
        } else if (value is List) {
          totalSize += value.length * 8; // 估算
        } else {
          totalSize += 8; // 基本类型估算
        }
      }

      return {
        'totalKeys': keys.length,
        'typeCount': typeCount,
        'estimatedSize': totalSize,
        'isEmpty': keys.isEmpty,
      };
    } catch (e) {
      logs.error('getStorageStats error: $e', tag: 'LaraPressKeyDB');
      return {};
    }
  }

  /// 清理过期数据（基于键名模式）
  Future<int> cleanupExpiredData(List<String> expiredKeyPatterns) async {
    try {
      await _ensureInitialized();
      int cleanedCount = 0;

      for (String key in _prefs!.getKeys()) {
        for (String pattern in expiredKeyPatterns) {
          if (key.contains(pattern)) {
            if (await remove(key)) {
              cleanedCount++;
            }
            break;
          }
        }
      }

      return cleanedCount;
    } catch (e) {
      logs.error('cleanupExpiredData error: $e', tag: 'LaraPressKeyDB');
      return 0;
    }
  }
}
